﻿#include "cvwidgetui.h"
#include "ui_cvwidgetui.h"

#include <QFileDialog>
#include <QThread>
#include <QDebug>

#include <vector>
#include <thread>
#include <atomic>

#include <opencv2/highgui.hpp>

#include "CvImageShow/include/ImageShow/Shapes.h"
//#include "QtOpenCV/cvmatandqimage.h"
#include "QtOpenCV/asmopencv.h"

cvwidgetui::cvwidgetui(QWidget *parent) :
    QFrame(parent),
    ui(new Ui::cvwidgetui)
{
    ui->setupUi(this);
    //Runing.store(0);
    std::atomic_init(&Runing, 0);
}

cvwidgetui::~cvwidgetui()
{
    if( Runing.load() == 1 )
    {
        Runing.store(2);
    }

    while(Runing.load() != 0)
    {
        std::this_thread::sleep_for(std::chrono::microseconds(10));
    }

    delete ui;
}

void cvwidgetui::ShowImage(bool JustShow, cv::Mat *pImage)
{
    if (!JustShow)
    {
//            if (m_IsDefectPic) //画缺陷 区域
//            {
//                //m_IsDefectPic = true;
//                cv::Rect DefectRoi(m_DefectX - 150, m_DefectY - 150, m_DefectW + 200, m_DefectH + 200);
//                cv::rectangle(*pImage, DefectRoi, cv::Scalar(0, 0, 255), 3, 8, 0);
//                stringstream wstream;
//                wstream << "defect :" << DefectRoi;
//                Log_Add(wstream.str());
//            }

    }

#if USE_EMBED_QT
        if (pImage == nullptr)
        {
            if (!pImage->empty())
            {
                ShowImageWithQt(*pImage);
            }
        }
        else
        {
            ShowImageWithQt(*pImage);
        }

#endif


    if (pImage != nullptr)//118585 20190501 静态分析问题
    {

        try{
            if (!ui->m_hImageCtrl->setShowImage(*pImage, false))//20171017 去掉这句整晚ok
            {
                qDebug() <<"setShowImage error!";
                //Log_Add(L"setShowImage error!");
            }

            ui->m_hImageCtrl->update();
        }
        catch(std::exception &e)
        {
            qDebug() <<"setShowImage:" << e.what();
        }

    }
}

//ROI 相关功能
//功能函数部分
void cvwidgetui::fnShowRoi( std::string id )
{
    float LaserOffset_X = 200;
    float LaserOffset_Y = 200;
    try
    {
        std::vector<cv::Point2f> vPoints;

        if( id.empty() )  //不新建则清除
        {
            for (int GroupInd = 0; GroupInd<ShapeGroups; GroupInd++)
            {
                int SubIteamId=0;
                for( ; ; )
                {
                    if( ui->m_hImageCtrl->getShapeArrayPtr()->FindShape(GroupInd, SubIteamId) == nullptr )
                    {
                        break;
                    }
                    ui->m_hImageCtrl->getShapeArrayPtr()->DeleteItem(GroupInd, SubIteamId);

                    SubIteamId++;

                    if( SubIteamId>100 )
                    {
                        break ;
                    }
                }
            }

            ui->m_hImageCtrl->update();
            return ;
        }

        if (id.find("Point") != std::string::npos)
        {
            vPoints.clear();
            vPoints.push_back(cv::Point2f(LaserOffset_X, LaserOffset_Y));
            int ind=0;
            for( ; ; )
            {
                if( ui->m_hImageCtrl->getShapeArrayPtr()->FindShape(ShapeGroupPoint, ind) == nullptr )
                {
                    break;
                }
                ind++;

                if( ind>100 )
                {
                    return ;
                }
            }
            std::string TypeNane = "Point";
            std::string ItemName = TypeNane+std::to_string(ind);
            ui->m_hImageCtrl->getShapeArrayPtr()->AddItem(TypeNane, ItemName, ShapeGroupPoint, ind, vPoints, 20, 220, 20, 0);
        }

        else if (id.find("Line") != std::string::npos)
        {
            vPoints.clear();
            vPoints.push_back(cv::Point2f(LaserOffset_X-100, LaserOffset_Y-100));
            vPoints.push_back(cv::Point2f(LaserOffset_X+100, LaserOffset_Y+100));

            int ind=0;
            for( ; ; )
            {
                if( ui->m_hImageCtrl->getShapeArrayPtr()->FindShape(ShapeGroupLine, ind) == nullptr )
                {
                    break;
                }
                ind++;

                if( ind>100 )
                {
                    return ;
                }
            }

            std::string TypeNane = "Line";
            std::string ItemName = TypeNane+std::to_string(ind);
            ui->m_hImageCtrl->getShapeArrayPtr()->AddItem(TypeNane, ItemName, ShapeGroupLine, ind, vPoints, 220, 220, 20, 0);
        }

        else if (id.find("Rect") != std::string::npos)
        {
            vPoints.clear();
            vPoints.push_back(cv::Point2f(LaserOffset_X-100, LaserOffset_Y-100));
            vPoints.push_back(cv::Point2f(LaserOffset_X+100, LaserOffset_Y+100));
            std::string TypeNane = "Rect";
            std::string ItemName = TypeNane+std::to_string(0);
            ui->m_hImageCtrl->getShapeArrayPtr()->AddItem(TypeNane, ItemName, ShapeGroupRect, 0, vPoints, 20, 220, 20, 0);
        }

        else if (id.find("Circle") != std::string::npos)
        {
            vPoints.push_back(cv::Point2f(LaserOffset_X, LaserOffset_Y));  //圆心
            vPoints.push_back(cv::Point2f(100, 0));  //r = sqrt(pow(x,2) + pow(y,2))/2
            std::string TypeNane = "Circle";
            std::string ItemName = TypeNane+std::to_string(0);
            ui->m_hImageCtrl->getShapeArrayPtr()->AddItem(TypeNane, ItemName, ShapeGroupCircle, 0, vPoints, 20, 220, 20, 0);
        }

//		else if (id.find("Polygon") != std::string::npos)
//		{
//			vPoints.clear();
//			m_PolygonPoints.clear(); //用来保存鼠标点击画多线的点位
//			SetBit(MouseMscOptions, CalLaserOffset, 0);
//			SetBit(MouseMscOptions, DrawPolygon, 1);
//			Log_Add("开始画多线", infoLog, true);
//		}

//        else if (id.find("Ruler") != std::string::npos)
//        {
//            if( ui->m_hImageCtrl->getShapeArrayPtr()->FindShape(ShapeGroupRuler, 0) == nullptr )
//            {
//                vPoints.push_back(cv::Point2f(LaserOffset_X - 100, LaserOffset_Y - 100));
//                vPoints.push_back(cv::Point2f(LaserOffset_X + 100, LaserOffset_Y + 100));

//                std::string TypeNane = "Ruler";
//                std::string ItemName = id;
//                ui->m_hImageCtrl->getShapeArrayPtr()->AddItem(TypeNane, ItemName, ShapeGroupRuler, 0, vPoints, 220, 220, 20, 0);
//                CvImageShow::Shapes::CShape* pRuler = m_hImageCtrl.getShapeArrayPtr()->FindShape(ShapeGroupRuler, 0);
//                ((CvImageShow::Shapes::CShapeRuler*)pRuler)->SetPixelRatio(g_sysConf.curMmPixel_x, g_sysConf.curMmPixel_y);
//            }
//            else
//            {
//                ui->m_hImageCtrl->getShapeArrayPtr()->DeleteItem(ShapeGroupRuler, 0);
//            }
//        }

        ui->m_hImageCtrl->update();
    }
    catch (std::exception &e)
    {
        qDebug()<<"fnShowRoi exception:"<<e.what();
        //Log_Add(std::string("fnShowRoi exception:")+e.what());
    }
}

void cvwidgetui::on_DirTestButton_clicked(bool checked)
{  
    if( Runing.load() == 1 )
    {
        Runing.store(2);
        return ;
    }
    //QUrl strFolderPath = QFileDialog::getExistingDirectoryUrl();
    QString strFolderPath = QFileDialog::getExistingDirectory();

    if (!strFolderPath.isEmpty())
    {
        Runing.store(1);
        std::string Pattern = (strFolderPath + "/*.bmp").toStdString();

        std::thread runThread = std::thread([&, Pattern](){
            std::vector<cv::String> NameVec;
            try {
                 cv::glob(Pattern, NameVec);
            }
            catch (cv::Exception &e)
            {
                qDebug() << e.what();
                return ;
            }

            while(1)
            {
                for (auto item : NameVec)
                {
                    if(Runing.load() == 2)
                    {
                        qDebug() << "end thread!";
                        Runing.store(0);
                        return ;
                    }

                    m_Image = cv::imread(item);
                    //qDebug() << item.c_str();
                    ShowImage(true, &m_Image);
                    //QThread::sleep(10);
                    std::this_thread::sleep_for(std::chrono::microseconds(10));
                }
            }
        });

        runThread.detach();
    }
}

void cvwidgetui::on_OpenImage_clicked()
{
    //QUrl strFolderPath = QFileDialog::getExistingDirectoryUrl();
    QString strFilePath = QFileDialog::getOpenFileName();

    if (!strFilePath.isEmpty())
    {
        std::string item = strFilePath.toStdString();

        try {
            m_Image = cv::imread(item);
        } catch (cv::Exception &e) {
            qDebug() <<"imread:"<< e.what();
        }

        try {
            ShowImage(true, &m_Image);
        } catch (std::exception &e) {
            qDebug() <<"ShowImage:"<< e.what();
        }
    }
}

void cvwidgetui::on_DrawLine_clicked()
{
    fnShowRoi( "Line" );;
}

void cvwidgetui::on_verticality_clicked()
{
    CvImageShow::Shapes::CShape* item = nullptr;
    item = ui->m_hImageCtrl->getShapeArrayPtr()->FindShape(ShapeGroupLine, 0);
    if(item == nullptr )
    {
        return ;
    }

    std::vector< cv::Point2f > m_PointVec;
    m_PointVec = item->GetPoints();

    if(m_PointVec.size() == 2)
    {
        std::vector<cv::Point2f> vPoints;
        vPoints.resize(2);
        auto Line = m_PointVec[1] - m_PointVec[0];
        vPoints[0] = (m_PointVec[1] + m_PointVec[0])/2;
        vPoints[1].x = vPoints[0].x+Line.y;
        vPoints[1].y = vPoints[0].y-Line.x;


        int ind = 1;
        std::string TypeNane = "Line";
        std::string ItemName = TypeNane+std::to_string(ind);
        ui->m_hImageCtrl->getShapeArrayPtr()->AddItem(TypeNane, ItemName, ShapeGroupLine, ind, vPoints, 220, 220, 20, 0);
    }
}

bool cvwidgetui::ShowImageSlot(const cv::Mat& ImgIn, const std::string Name)
{
    m_Image = ImgIn.clone();
    ShowImage(true, &m_Image);
    return true;
}

void cvwidgetui::UpdateIconListSlot(const std::map<std::string, cv::Mat> Images, const std::string objectName)
{
    CurrentObiectName = objectName;
    ui->ImageList->clear();
    std::map<std::string, cv::Mat>::const_iterator iter = Images.begin();
    while(iter != Images.end())
    {
        cv::Mat Tmp;
        cv::resize(iter->second, Tmp, cv::Size(128,128));

        //m_QImageList[iter->first] = QtOcv::mat2Image_shared(Tmp);
        m_QImageList[iter->first] = ASM::cvMatToQImage(Tmp);
        //cout << iter->first << " : " << iter->second << endl;

        QListWidgetItem *item = new QListWidgetItem(iter->first.c_str(), ui->ImageList);
        item->setData(Qt::DecorationRole, QPixmap::fromImage(m_QImageList[iter->first]));

        iter++;
    }
}

bool cvwidgetui::AddImageSlot(const cv::Mat& image, const std::string Name)
{
    if(!image.empty())
    {
        cv::Mat Tmp;
        cv::resize(image, Tmp, cv::Size(128,128));
        m_QImageList[Name] = ASM::cvMatToQImage(Tmp);

        QListWidgetItem *item = new QListWidgetItem(Name.c_str(), ui->ImageList);
        item->setData(Qt::DecorationRole, QPixmap::fromImage(m_QImageList[Name]));

        m_OrgImageList[Name] = image;
        qDebug() << u8"添加图片:" << Name.c_str();
        return true;
    }
    else
    {
        qWarning() << u8"添加图片为空！"<<Name.c_str();
        return false;
    }
}

void cvwidgetui::on_ImageList_currentTextChanged(const QString &currentText)
{
    if(m_OrgImageList.find(currentText.toUtf8().data()) == m_OrgImageList.end())
    {
        SlectectImageToShowSig(currentText.toStdString(), CurrentObiectName);
    }
    else
    {
        ShowImageSlot( m_OrgImageList[currentText.toUtf8().data()], currentText.toUtf8().data());
    }
}
